require "client.client"

--- separated moves to many moves(one card per move)
---@param moves CardsMoveStruct[]
local function separateMoves(moves)
  local ret = {}  ---@type CardsMoveInfo[]

  local function containArea(area, relevant, defaultVisible) --处理区的处理？
    local areas = relevant
      and {Card.PlayerEquip, Card.PlayerJudge, Card.PlayerHand}
      or {Card.PlayerEquip, Card.PlayerJudge}
    return table.contains(areas, area) or (defaultVisible and table.contains({Card.Processing, Card.DiscardPile}, area))
  end

  for _, move in ipairs(moves) do
    local singleVisible = move.moveVisible
    if not singleVisible then
      if move.visiblePlayers then
        local visiblePlayers = move.visiblePlayers
        if type(visiblePlayers) == "number" then
          if Self:isBuddy(visiblePlayers) then
            singleVisible = true
          end
        elseif type(visiblePlayers) == "table" then
          if table.find(visiblePlayers, function(pid) return Self:isBuddy(pid) end) then
            singleVisible = true
          end
        end
      else
        if move.to and move.toArea == Card.PlayerSpecial and Self:isBuddy(move.to) then
          singleVisible = true
        end
      end
    end
    if not singleVisible then
      singleVisible = containArea(move.toArea, move.to and Self:isBuddy(move.to), move.moveVisible == nil)
    end

    for _, info in ipairs(move.moveInfo) do
      table.insert(ret, {
        ids = {info.cardId},
        from = move.from,
        to = move.to,
        toArea = move.toArea,
        fromArea = info.fromArea,
        moveReason = move.moveReason,
        specialName = move.specialName,
        fromSpecialName = info.fromSpecialName,
        proposer = move.proposer,
        moveVisible = singleVisible or containArea(info.fromArea, move.from and Self:isBuddy(move.from), move.moveVisible == nil)
      })
    end
  end
  return ret
end

--- merge separated moves that information is the same
local function mergeMoves(moves)
  local ret = {}
  local temp = {}
  for _, move in ipairs(moves) do
    local info = string.format("%q,%q,%q,%q,%s,%s,%q",
      move.from, move.to, move.fromArea, move.toArea,
      move.specialName, move.fromSpecialName, move.proposer)
    if temp[info] == nil then
      temp[info] = {
        ids = {},
        from = move.from,
        to = move.to,
        fromArea = move.fromArea,
        toArea = move.toArea,
        moveReason = move.moveReason,
        specialName = move.specialName,
        fromSpecialName = move.fromSpecialName,
        proposer = move.proposer,
      }
    end
    -- table.insert(temp[info].ids, move.moveVisible and move.ids[1] or -1)
    table.insert(temp[info].ids, move.ids[1])
  end
  for _, v in pairs(temp) do
    table.insert(ret, v)
  end
  return ret
end

fk.client_callback = fk.client_callback or {}
---@param raw_moves CardsMoveStruct[]
fk.client_callback["MoveCardsWithoutLog"] = function(raw_moves)
  -- jsonData: CardsMoveStruct[]
  ClientInstance:moveCards(raw_moves)
  local visible_data = {}
  for _, move in ipairs(raw_moves) do
    for _, info in ipairs(move.moveInfo) do
      local cid = info.cardId
      visible_data[tostring(cid)] = Self:cardVisible(cid, move)
    end
  end
  local separated = separateMoves(raw_moves)
  local merged = mergeMoves(separated)
  visible_data.merged = merged
  ClientInstance:notifyUI("MoveCards", visible_data)
end